﻿/**
*    Copyright (C) 2008  Chase Kernan 
*    chase.kernan@gmail.com
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
* 
**/

package com.chasekernan.hxnova.componenteditor;

import flash.events.Event;
import flash.net.DynamicPropertyOutput;
import org.aswing.border.EmptyBorder;
import org.aswing.border.TitledBorder;
import org.aswing.event.ListItemEvent;
import org.aswing.Insets;
import org.aswing.JButton;
import org.aswing.JFrame;
import com.chasekernan.hxnova.core.components.ComponentSet;
import com.chasekernan.hxnova.core.components.ComponentTypeSet;
import org.aswing.JLabel;
import org.aswing.JList;
import org.aswing.JPanel;
import org.aswing.SoftBox;
import org.aswing.SoftBoxLayout;
import org.aswing.GridLayout;
import org.aswing.geom.IntDimension;
import org.aswing.JTextField;
import org.aswing.JOptionPane;

class EditComponentTypeSets extends JFrame {
	
	public static var CLOSE = "close";
    
    private var typeSetList : JList;
    private var componentTypes : JList;
    private var addButton : JButton;
    private var removeButton : JButton;
    private var includedComponents : JList;
    private var newTypeSetButton : JButton;
    private var removeTypeSetButton : JButton;
    
    private var newTypeSetWindow : NewTypeSetWindow;
    
    //these are used to keep track of the components, as removing items
    //from a list uses an as3 list type which is kinda contrived in haxe.
    private var availableComponentsArray : Array<String>;
    private var includedComponentsArray : Array<String>;
    
    private var currentTypeSet : ComponentTypeSet;
    
    public function new(?parent : Dynamic) {
        super(parent, "Edit Component Type Sets", true);
        
        setContentPane(setupContents());
        
        componentTypes.setPreferredWidth(150);
        includedComponents.setPreferredWidth(150);
        
        pack();
        
        addButton.addActionListener(onClickAdd);
        removeButton.addActionListener(onClickRemove);
        newTypeSetButton.addActionListener(onClickNewTypeSet);
        typeSetList.addEventListener(ListItemEvent.ITEM_CLICK, onClickTypeSetList);
        removeTypeSetButton.addActionListener(onClickRemoveTypeSet);
        addEventListener(Event.ENTER_FRAME, saveToComponentTypeSet);
        
        updateComponentTypeSets();
        
        setAllEnabled(false);
        currentTypeSet = null;
    }
    
    private function setupContents() : JPanel {
        availableComponentsArray = ComponentEditorPanel.getComponentClassNames();
        includedComponentsArray = new Array();
        
        var contents = new JPanel();
        
        var typeSetPanel = new SoftBox(SoftBoxLayout.Y_AXIS, 5);
        typeSetPanel.setBorder(createTitledBorder("Component Type Sets"));
        typeSetList = new JList();
        typeSetPanel.append(typeSetList);
        
        //small panel to store the buttons side by side
        var buttonPanel = new JPanel();
        newTypeSetButton = new JButton("New Type Set");
        buttonPanel.append(newTypeSetButton);
        removeTypeSetButton = new JButton("Remove Type Set");
        buttonPanel.append(removeTypeSetButton);
        typeSetPanel.append(buttonPanel);
        
        contents.append(typeSetPanel);
        
        //initially contains all of the component types
        var componentTypesPanel = new SoftBox(SoftBoxLayout.Y_AXIS, 5);
        componentTypesPanel.setBorder(createTitledBorder("Available Component Types"));
        componentTypes = new JList(availableComponentsArray);
        componentTypesPanel.append(componentTypes);
        addButton = new JButton("Add");
        componentTypesPanel.append(addButton);
        contents.append(componentTypesPanel);
        
        var includedComponentsPanel = new SoftBox(SoftBoxLayout.Y_AXIS, 5);
        includedComponentsPanel.setBorder(createTitledBorder("Included Components"));
        includedComponents = new JList();
        includedComponentsPanel.append(includedComponents);
        removeButton = new JButton("Remove");
        includedComponentsPanel.append(removeButton);
        contents.append(includedComponentsPanel);
        
        return contents;
    }
    
    private function onClickAdd(?e : Dynamic) {
        if (componentTypes.getSelectedValue() == null) return;
        var selection = cast(componentTypes.getSelectedValue(), String);
        
        includedComponentsArray.push(selection);
        includedComponents.setListData(includedComponentsArray);
        
        availableComponentsArray.remove(selection);
        componentTypes.setListData(availableComponentsArray);
    }
    
    private function onClickRemove(?e : Dynamic) {
        if (includedComponents.getSelectedValue() == null) return;
        var selection = cast(includedComponents.getSelectedValue(), String);
        
        includedComponentsArray.remove(selection);
        includedComponents.setListData(includedComponentsArray);
        
        availableComponentsArray.push(selection);
        componentTypes.setListData(availableComponentsArray);
    }
    
    private function updateComponentTypeSets(?e : Dynamic) {
        var names = new Array<String>();
        for (cts in ComponentSet.COMPONENT_TYPE_SETS) names.push(cts.name);
        typeSetList.setListData(names);
    }
    
    private function onClickNewTypeSet(?e : Dynamic) {
        saveToComponentTypeSet();
        
        newTypeSetWindow = new NewTypeSetWindow();
        newTypeSetWindow.addEventListener(NewTypeSetWindow.OK, onCreateNewTypeSet);
        newTypeSetWindow.show();
    }
    
    private function onCreateNewTypeSet(?e : Dynamic) {
        setAllEnabled(true);
        
        var newName = newTypeSetWindow.getTypeSetName();
        
        currentTypeSet = new ComponentTypeSet(newName);
        ComponentSet.addComponentTypeSet(currentTypeSet);
        updateComponentTypeSets();
        loadFromComponentTypeSet();
        
        typeSetList.setSelectedValue(newName);
        
        newTypeSetWindow.tryToClose();
        newTypeSetWindow = null;
    }
    
    private function onClickRemoveTypeSet(?e : Dynamic) {
        saveToComponentTypeSet();
        
        var selection = typeSetList.getSelectedValue();
        if (selection == null) return;
        
        ComponentSet.removeComponentTypeSet(ComponentSet.getComponentTypeSetByName(selection));
        updateComponentTypeSets();
        
        setAllEnabled(false);
        currentTypeSet = null;
    }
    
    private function loadFromComponentTypeSet(?e : Dynamic) {
        if (currentTypeSet == null) return;
        
        availableComponentsArray = ComponentEditorPanel.getComponentClassNames();
        includedComponentsArray = new Array();
        
        for (componentType in currentTypeSet.types) {
            var name = ComponentEditorPanel.getClassString(componentType);
            availableComponentsArray.remove(name);
            includedComponentsArray.push(name);
        }
        
        componentTypes.setListData(availableComponentsArray);
        includedComponents.setListData(includedComponentsArray);
        
        setAllEnabled(true);
    }
    
    private function saveToComponentTypeSet(?e : Dynamic) {
        if (currentTypeSet == null) return;
        if (includedComponentsArray == null) return;
        
        currentTypeSet.types = new Array();
        for (typeName in includedComponentsArray) {
            currentTypeSet.addType(Type.resolveClass(
                "com.chasekernan.hxnova.core.components." + typeName));
        }
    }
    
    private function setAllEnabled(enabled : Bool) {
        addButton.setEnabled(enabled);
        removeButton.setEnabled(enabled);
        componentTypes.setEnabled(enabled);
        includedComponents.setEnabled(enabled);
    }
    
    private function onClickTypeSetList(e : ListItemEvent) {
        setAllEnabled(true);
        
        saveToComponentTypeSet();
        currentTypeSet = ComponentSet.getComponentTypeSetByName(e.getCell().getCellValue());
        loadFromComponentTypeSet();
    }
    
    public override function tryToClose() {
        saveToComponentTypeSet();
		dispatchEvent(new Event(CLOSE));
        super.tryToClose();
    }
        
    
    private static function createTitledBorder(name : String) : EmptyBorder {
        return new EmptyBorder(
                   new TitledBorder(
                       new EmptyBorder(null, 
                           new Insets(5, 5, 5, 5)), 
                           name), 
                           new Insets(5, 5, 5, 5));
    }
    
}

class NewTypeSetWindow extends JFrame {
    
    public static var OK : String = "ok";
    
    private var nameInput : JTextField;
    private var okButton : JButton;
    private var cancelButton : JButton;
    
    public function new(?parent : Dynamic) {
        super(parent, "New Component", true);
        
        setContentPane(setupContents());
        setLocationXY(100, 225);
        pack();
        
        okButton.addActionListener(onOK);
        cancelButton.addActionListener(onCancel);
    }
    
    private function setupContents() : JPanel {
        var contents : JPanel = new JPanel(new GridLayout(2, 2, 5, 5));
        contents.setBorder(new EmptyBorder(new Insets(5, 5, 5, 5)));
               
        contents.append(ComponentEditorPanel.setupDefaultLabel("Name"));
        nameInput = new JTextField("Name");
        nameInput.setMaxChars(30);
        contents.append(nameInput);
        contents.append(new JLabel(""));
        
        okButton = new JButton("OK");
        contents.append(okButton);
        cancelButton = new JButton("Cancel");
        contents.append(cancelButton);
        
        return contents;
    }
    
    public function getTypeSetName() : String {
        return nameInput.getText();
    }
    
    private function onOK(?e : Dynamic) {
        for (typeSet in ComponentSet.COMPONENT_TYPE_SETS) {
            if (typeSet.name == getTypeSetName()) {
                JOptionPane.showMessageDialog("Error", "This name is already in use, please choose another.");
                return;
            }
        }
        dispatchEvent(new Event(OK));
    }
    
    private function onCancel(?e : Dynamic) {
        tryToClose();
    }
}